package sdmakerz_v1.coresyntax.generator;

import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.IteratorExtensions;
import sdmakerz_v1.coresyntax.SDMakerV1Utils;
import sdmakerz_v1.coresyntax.generator.InterfaceDataImpl;
import sdmakerz_v1.coresyntax.generator.SDMakerV1IDProvider;
import sdmakerz_v1.coresyntax.generator.interfaces.IConfigData;
import sdmakerz_v1.coresyntax.generator.interfaces.IContext;
import sdmakerz_v1.coresyntax.generator.interfaces.IDiagramRefData;
import sdmakerz_v1.coresyntax.generator.interfaces.IInputData;
import sdmakerz_v1.coresyntax.generator.interfaces.IInterfaceData;
import sdmakerz_v1.coresyntax.io.SDMakerIO;
import sdmakerz_v1.coresyntax.sDMakerV1.Call;
import sdmakerz_v1.coresyntax.sDMakerV1.Config;
import sdmakerz_v1.coresyntax.sDMakerV1.Diagram;
import sdmakerz_v1.coresyntax.sDMakerV1.Obj;
import sdmakerz_v1.coresyntax.sDMakerV1.Reference;
import sdmakerz_v1.coresyntax.sDMakerV1.Type;

/**
 * @author pstl-team
 */
@SuppressWarnings("all")
public class ContextImpl implements IContext {
  /**
   * La resource qui contient les donnees du fichier sdmaker traite
   */
  private IInputData inputData;
  
  /**
   * Les donnees de configuration du contexte
   */
  private IConfigData configData;
  
  /**
   * Les donnees pour le renommage des variables
   */
  private IDiagramRefData diagramRefData;
  
  /**
   * Les donnees liant les interfaces et leurs instances
   */
  private List<IInterfaceData> interfacesDatas;
  
  private Diagram contextDiagram;
  
  /**
   * *** INITIALIZERS ***
   */
  public void init() {
    try {
      List<String> types = this.findAllTypeQualifiedName();
      SDMakerIO _sDMakerIO = new SDMakerIO();
      SDMakerIO sdmakerIO = _sDMakerIO;
      List<IInputData> inputDatas = sdmakerIO.allInputs();
      this.inputData = null;
      this.configData = null;
      this.diagramRefData = null;
      this.contextDiagram = null;
      ArrayList<IInterfaceData> _arrayList = new ArrayList<IInterfaceData>();
      this.interfacesDatas = _arrayList;
      for (final String type : types) {
        this.addNewType(type);
      }
      int _computeID = SDMakerV1IDProvider.computeID();
      SDMakerV1IDProvider.setMinimalIDNumber(_computeID);
      SDMakerV1IDProvider.reinitIDs();
      for (final IInputData inputDTmp : inputDatas) {
        {
          this.inputData = inputDTmp;
          Resource _input = this.inputData.getInput();
          TreeIterator<EObject> _allContents = _input.getAllContents();
          Iterable<EObject> _iterable = IteratorExtensions.<EObject>toIterable(_allContents);
          Iterable<Obj> _filter = Iterables.<Obj>filter(_iterable, Obj.class);
          for (final Obj obj : _filter) {
            this.bindObjWithInterface(obj);
          }
          Resource _input_1 = this.inputData.getInput();
          TreeIterator<EObject> _allContents_1 = _input_1.getAllContents();
          Iterable<EObject> _iterable_1 = IteratorExtensions.<EObject>toIterable(_allContents_1);
          Iterable<Call> _filter_1 = Iterables.<Call>filter(_iterable_1, Call.class);
          for (final Call call : _filter_1) {
            this.bindCallWithInterface(call);
          }
        }
      }
      this.cleanContext();
    } catch (Exception _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  /**
   * *** SETTERS ***
   */
  public void setInput(final IInputData inputData) {
    this.inputData = inputData;
  }
  
  public void setContextDiagram(final Diagram contextDiagram) {
    this.contextDiagram = contextDiagram;
  }
  
  public void setConfigData(final IConfigData configData) {
    this.configData = configData;
  }
  
  public void setDiagramRefData(final IDiagramRefData diagramRefData) {
    this.diagramRefData = diagramRefData;
  }
  
  public void cleanContext() {
    this.inputData = null;
    this.contextDiagram = null;
    this.configData = null;
    this.diagramRefData = null;
  }
  
  public void addNewType(final String typeQualifiedName) {
    InterfaceDataImpl _interfaceDataImpl = new InterfaceDataImpl();
    IInterfaceData iid = _interfaceDataImpl;
    iid.init();
    iid.setName(typeQualifiedName);
    String _replaceAll = typeQualifiedName.replaceAll("\\.", "_");
    String _plus = (_replaceAll + 
      "Class_id");
    int _computeID = SDMakerV1IDProvider.computeID();
    String _plus_1 = (_plus + Integer.valueOf(_computeID));
    iid.setInterfaceID(_plus_1);
    this.interfacesDatas.add(iid);
  }
  
  public void bindObjWithInterface(final Obj obj) {
    Resource _input = this.inputData.getInput();
    Type _type = obj.getType();
    String _identifier = _type.getIdentifier();
    List<String> types = SDMakerV1Utils.findMatchingQualifiedNames(_input, _identifier);
    int _size = types.size();
    boolean _equals = (_size == 1);
    if (_equals) {
      for (final IInterfaceData iid : this.interfacesDatas) {
        String _qualifiedName = iid.getQualifiedName();
        String _get = types.get(0);
        int _compareTo = _qualifiedName.compareTo(_get);
        boolean _equals_1 = (_compareTo == 0);
        if (_equals_1) {
          iid.addObj(obj);
        }
      }
    }
  }
  
  public void bindCallWithInterface(final Call c) {
    EObject eo = SDMakerV1Utils.findContainer(c, Diagram.class);
    Diagram d = ((Diagram) eo);
    Obj called = null;
    List<String> types = null;
    IInterfaceData iid = null;
    boolean _notEquals = (!Objects.equal(d, null));
    if (_notEquals) {
      TreeIterator<EObject> _eAllContents = d.eAllContents();
      Iterable<EObject> _iterable = IteratorExtensions.<EObject>toIterable(_eAllContents);
      Iterable<Obj> _filter = Iterables.<Obj>filter(_iterable, Obj.class);
      for (final Obj obj : _filter) {
        String _name = obj.getName();
        String _called = c.getCalled();
        int _compareTo = _name.compareTo(_called);
        boolean _equals = (_compareTo == 0);
        if (_equals) {
          called = obj;
        }
      }
      boolean _notEquals_1 = (!Objects.equal(called, null));
      if (_notEquals_1) {
        Resource _input = this.inputData.getInput();
        Type _type = called.getType();
        String _identifier = _type.getIdentifier();
        List<String> _findMatchingQualifiedNames = SDMakerV1Utils.findMatchingQualifiedNames(_input, _identifier);
        types = _findMatchingQualifiedNames;
        int _size = types.size();
        boolean _equals_1 = (_size == 1);
        if (_equals_1) {
          String _get = types.get(0);
          IInterfaceData _interfaceDataByName = this.getInterfaceDataByName(_get);
          iid = _interfaceDataByName;
        }
        boolean _notEquals_2 = (!Objects.equal(iid, null));
        if (_notEquals_2) {
          iid.addCall(this.inputData, c);
        }
      }
    }
  }
  
  /**
   * *** GETTERS ***
   */
  public IInputData getInputData() {
    return this.inputData;
  }
  
  public IConfigData getConfigData() {
    return this.configData;
  }
  
  public IDiagramRefData getDiagramRefData() {
    return this.diagramRefData;
  }
  
  public List<IInterfaceData> getInterfacesDatas() {
    return this.interfacesDatas;
  }
  
  public IInterfaceData getInterfaceDataByName(final String name) {
    IInterfaceData foundedInterfaceDatas = null;
    String qualifiedName = null;
    Resource _input = this.inputData.getInput();
    List<String> matchingQualifiedName = SDMakerV1Utils.findMatchingQualifiedNames(_input, name);
    int _size = matchingQualifiedName.size();
    boolean _equals = (_size == 1);
    if (_equals) {
      String _get = matchingQualifiedName.get(0);
      qualifiedName = _get;
      for (final IInterfaceData interfaceDatas : this.interfacesDatas) {
        String _qualifiedName = interfaceDatas.getQualifiedName();
        int _compareTo = _qualifiedName.compareTo(qualifiedName);
        boolean _equals_1 = (_compareTo == 0);
        if (_equals_1) {
          foundedInterfaceDatas = interfaceDatas;
        }
      }
    }
    return foundedInterfaceDatas;
  }
  
  public IInterfaceData getInterfaceDataByObject(final Obj obj) {
    IInterfaceData iid = null;
    for (final IInterfaceData interfaceData : this.interfacesDatas) {
      Boolean _contains = interfaceData.contains(obj);
      if ((_contains).booleanValue()) {
        iid = interfaceData;
      }
    }
    return iid;
  }
  
  public IInterfaceData getInterfaceDataByObjectName(final String objName) {
    IInterfaceData iid = null;
    Obj obj = null;
    boolean _notEquals = (!Objects.equal(this.contextDiagram, null));
    if (_notEquals) {
      TreeIterator<EObject> _eAllContents = this.contextDiagram.eAllContents();
      Iterable<EObject> _iterable = IteratorExtensions.<EObject>toIterable(_eAllContents);
      Iterable<Obj> _filter = Iterables.<Obj>filter(_iterable, Obj.class);
      for (final Obj objTmp : _filter) {
        String _name = objTmp.getName();
        int _compareTo = _name.compareTo(objName);
        boolean _equals = (_compareTo == 0);
        if (_equals) {
          obj = objTmp;
        }
      }
      boolean _notEquals_1 = (!Objects.equal(obj, null));
      if (_notEquals_1) {
        IInterfaceData _interfaceDataByObject = this.getInterfaceDataByObject(obj);
        iid = _interfaceDataByObject;
      }
    }
    return iid;
  }
  
  public Diagram findDiagram(final Reference diagRef) {
    try {
      SDMakerIO _sDMakerIO = new SDMakerIO();
      SDMakerIO sdmakerIO = _sDMakerIO;
      Diagram diag = sdmakerIO.findDiagramWithImport(diagRef);
      return diag;
    } catch (Exception _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  public Resource findDiagramInput(final Reference diagRef) {
    try {
      SDMakerIO _sDMakerIO = new SDMakerIO();
      SDMakerIO sdmakerIO = _sDMakerIO;
      Diagram _findDiagramWithImport = sdmakerIO.findDiagramWithImport(diagRef);
      Resource diagInput = _findDiagramWithImport.eResource();
      return diagInput;
    } catch (Exception _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  public Config findConfig(final Reference confRef) {
    try {
      SDMakerIO _sDMakerIO = new SDMakerIO();
      SDMakerIO sdmakerIO = _sDMakerIO;
      Resource _input = this.inputData.getInput();
      Config config = sdmakerIO.findConfigWithImports(_input, confRef);
      return config;
    } catch (Exception _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  public List<String> findAllTypeQualifiedName() {
    try {
      SDMakerIO _sDMakerIO = new SDMakerIO();
      SDMakerIO sdmakerIO = _sDMakerIO;
      List<IInputData> inputs = sdmakerIO.allInputs();
      ArrayList<String> _arrayList = new ArrayList<String>();
      List<String> types = _arrayList;
      for (final IInputData inputDTmp : inputs) {
        {
          Resource inputTmp = inputDTmp.getInput();
          TreeIterator<EObject> _allContents = inputTmp.getAllContents();
          Iterable<EObject> _iterable = IteratorExtensions.<EObject>toIterable(_allContents);
          Iterable<Obj> _filter = Iterables.<Obj>filter(_iterable, Obj.class);
          for (final Obj obj : _filter) {
            {
              Type _type = obj.getType();
              String _identifier = _type.getIdentifier();
              List<String> matchingQualifiedName = SDMakerV1Utils.findMatchingQualifiedNames(inputTmp, _identifier);
              int _size = matchingQualifiedName.size();
              boolean _equals = (_size == 1);
              if (_equals) {
                String _get = matchingQualifiedName.get(0);
                boolean _contains = SDMakerV1Utils.contains(types, _get);
                boolean _equals_1 = (_contains == false);
                if (_equals_1) {
                  String _get_1 = matchingQualifiedName.get(0);
                  types.add(_get_1);
                }
              }
            }
          }
        }
      }
      return types;
    } catch (Exception _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
}
